#!/usr/bin/python

#Audio Tools, a module and set of tools for manipulating audio data
#Copyright (C) 2007  Brian Langenberger

#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


import sys
import audiotools
import os.path,optparse

def blank_metadata(track, xmcd):
    return audiotools.MetaData()

def track_metadata(track, xmcd):
    return track.get_metadata()

def xmcd_metadata(track, xmcd):
    metadata = xmcd[track.track_number()]
    if (metadata != None):
        return metadata
    else:
        return audiotools.MetaData()

def xmcd_track_metadata(track, xmcd):
    xmcd_metadata = xmcd[track.track_number()]
    if (xmcd_metadata != None):
        #xmcd data overwrites whatever comes from track
        #(so longs as it's not blank)
        track_metadata = track.get_metadata()

        for field in ('track_name','track_number','album_name',
                      'artist_name','performer_name','copyright',
                      'year'):
            if (getattr(xmcd_metadata,field) != u""):
                setattr(track_metadata,field,
                        getattr(xmcd_metadata,field))
        return track_metadata
    else:
        return track.get_metadata()

#tries to return a populated Image object of the appropriate type
#raises InvalidImage if something goes wrong during opening or parsing
def get_image(filename, type):
    try:
        f = open(filename,'rb')
        data = f.read()
        f.close()

        return audiotools.Image.new(data,u'',type)
    except IOError:
        raise audiotools.InvalidImage("error opening file: \"%s\"" % (filename))


if (__name__ == '__main__'):
    parser = optparse.OptionParser(
        "%prog [-x XMCD file] <track 1> [track 2] ...",
        version="Python Audio Tools %s" % (audiotools.VERSION))

    parser.add_option('--name',
                      action='store',
                      type='string',
                      dest='track_name',
                      help="the name of the track")

    parser.add_option('--number',
                      action='store',
                      type='int',
                      dest='track_number',
                      help="the number of the track in the album")

    parser.add_option('--album',
                      action='store',
                      type='string',
                      dest='album_name',
                      help='the name of the album')

    parser.add_option('--artist',
                      action='store',
                      type='string',
                      dest='artist_name',
                      help='the name of the artist')

    parser.add_option('--performer',
                      action='store',
                      type='string',
                      dest='performer_name',
                      help='the name of the performer')

    parser.add_option('--copyright',
                      action='store',
                      type='string',
                      dest='copyright',
                      help='copyright information')

    parser.add_option('--year',
                      action='store',
                      type='string',
                      dest='year',
                      help='the year of release')

    parser.add_option('-r','--replace',
                      action='store_true',
                      default=False,
                      dest='replace',
                      help='completely replace all metadata')

    parser.add_option('-x','--xmcd',
                      action='store',
                      type='string',
                      dest='xmcd',
                      help='an XMCD file to get audio metadata from',
                      metavar='FILENAME')

    parser.add_option('--remove-images',
                      action='store_true',
                      default=False,
                      dest='remove_images',
                      help='remove existing images prior to adding new ones')

    parser.add_option('--front-cover',
                      action='append',
                      type='string',
                      dest='front_cover',
                      help='an image file of the front cover',
                      metavar='FILENAME')

    parser.add_option('--back-cover',
                      action='append',
                      type='string',
                      dest='back_cover',
                      help='an image file of the back cover',
                      metavar='FILENAME')

    parser.add_option('--leaflet',
                      action='append',
                      type='string',
                      dest='leaflet',
                      help='an image file of a leaflet page',
                      metavar='FILENAME')

    parser.add_option('--media',
                      action='append',
                      type='string',
                      dest='media',
                      help='an image file of the media',
                      metavar='FILENAME')

    parser.add_option('--other-image',
                      action='append',
                      type='string',
                      dest='other_image',
                      help='an image file related to the track',
                      metavar='FILENAME')

    parser.add_option('--replay-gain',
                      action='store_true',
                      default=False,
                      dest='add_replay_gain',
                      help='add ReplayGain metadata to track(s)')

    (options,args) = parser.parse_args()

    audiofiles = audiotools.open_files(args)

    if (options.xmcd != None):
        try:
            xmcd = audiotools.parse_xmcd_file(options.xmcd)
        except audiotools.XMCDException:
            print >>sys.stderr,"*** Error opening XMCD file \"%s\"" % \
                  (options.xmcd)
            sys.exit(1)
    else:
        xmcd = None

    if (options.replace):
        if (xmcd == None):
            metadata_function = blank_metadata
        else:
            metadata_function = xmcd_metadata
    else:
        if (xmcd == None):
            metadata_function = track_metadata
        else:
            metadata_function = xmcd_track_metadata


    for file in audiofiles:
        metadata = metadata_function(file, xmcd)

        if (metadata is not None):
            try:
                for field in ('track_name','track_number','album_name',
                              'artist_name','performer_name','copyright',
                              'year'):
                    if (getattr(options,field) != None):
                        attr = getattr(options,field)
                        if (isinstance(attr,str)):
                            attr = attr.decode(audiotools.IO_ENCODING)
                        setattr(metadata,field,attr)


                if (metadata.supports_images()):
                    if (options.remove_images):
                        for i in metadata.images():
                            metadata.delete_image(i)

                    if (options.front_cover is not None):
                        for path in options.front_cover:
                            metadata.add_image(get_image(path,0))

                    if (options.leaflet is not None):
                        for path in options.leaflet:
                            metadata.add_image(get_image(path,2))

                    if (options.back_cover is not None):
                        for path in options.back_cover:
                            metadata.add_image(get_image(path,1))

                    if (options.media is not None):
                        for path in options.media:
                            metadata.add_image(get_image(path,3))

                    if (options.other_image is not None):
                        for path in options.other_image:
                            metadata.add_image(get_image(path,4))

                file.set_metadata(metadata)
            except audiotools.InvalidImage,msg:
                print >>sys.stderr,"* %s: %s" % (file.filename,msg)
                sys.exit(1)

    #we're assuming all tracks are the same type
    if (options.add_replay_gain and
        (len(audiofiles) > 0) and
        (audiofiles[0].can_add_replay_gain())):
        print >>sys.stderr,"* Adding ReplayGain metadata.  This may take some time."
        audiofiles[0].add_replay_gain([f.filename for f in audiofiles])
